import 'package:flutter/material.dart';
import 'dart:ui' as ui;

enum WrapMode { word, character }

class CustomTextPainter extends CustomPainter {
  final String text;
  final TextStyle style;
  final WrapMode wrapMode;
  final double? maxWidth;
  final String? fontFamily;
  final FontWeight? fontWeight;
  final FontStyle? fontStyle;

  CustomTextPainter({
    required this.text,
    required this.style,
    required this.wrapMode,
    this.maxWidth,
    this.fontFamily,
    this.fontWeight,
    this.fontStyle,
  });

  TextStyle get _effectiveStyle {
    return style.copyWith(
      fontFamily: fontFamily,
      fontWeight: fontWeight,
      fontStyle: fontStyle,
    );
  }

  @override
  void paint(Canvas canvas, Size size) {
    if (wrapMode == WrapMode.word) {
      _paintWordWrap(canvas, size);
    } else {
      _paintCharacterWrap(canvas, size);
    }
  }

  void _paintWordWrap(Canvas canvas, Size size) {
    final textPainter = TextPainter(
      text: TextSpan(text: text, style: _effectiveStyle),
      textDirection: TextDirection.ltr,
      maxLines: null,
      textWidthBasis: TextWidthBasis.parent,
    );

    textPainter.layout(maxWidth: maxWidth ?? size.width);
    textPainter.paint(canvas, Offset.zero);
  }

  void _paintCharacterWrap(Canvas canvas, Size size) {
    final characters = text.split('');
    double currentX = 0;
    double currentY = 0;
    final lineHeight = _effectiveStyle.fontSize! * (_effectiveStyle.height ?? 1.0);
    final effectiveMaxWidth = maxWidth ?? size.width;

    for (var char in characters) {
      final textPainter = TextPainter(
        text: TextSpan(text: char, style: _effectiveStyle),
        textDirection: TextDirection.ltr,
      );

      textPainter.layout();

      if (currentX + textPainter.width > effectiveMaxWidth) {
        currentX = 0;
        currentY += lineHeight;
      }

      textPainter.paint(canvas, Offset(currentX, currentY));
      currentX += textPainter.width;
    }
  }

  Size getTextSize(double maxWidth) {
    if (wrapMode == WrapMode.word) {
      final textPainter = TextPainter(
        text: TextSpan(text: text, style: _effectiveStyle),
        textDirection: TextDirection.ltr,
        maxLines: null,
        textWidthBasis: TextWidthBasis.parent,
      );
      textPainter.layout(maxWidth: maxWidth);
      return textPainter.size;
    } else {
      final characters = text.split('');
      double currentX = 0;
      double currentY = 0;
      double maxLineWidth = 0;
      final lineHeight = _effectiveStyle.fontSize! * (_effectiveStyle.height ?? 1.0);

      for (var char in characters) {
        final textPainter = TextPainter(
          text: TextSpan(text: char, style: _effectiveStyle),
          textDirection: TextDirection.ltr,
        );
        textPainter.layout();

        if (currentX + textPainter.width > maxWidth) {
          maxLineWidth = maxLineWidth > currentX ? maxLineWidth : currentX;
          currentX = 0;
          currentY += lineHeight;
        }
        currentX += textPainter.width;
      }
      maxLineWidth = maxLineWidth > currentX ? maxLineWidth : currentX;
      return Size(maxLineWidth, currentY + lineHeight);
    }
  }

  @override
  bool shouldRepaint(covariant CustomTextPainter oldDelegate) {
    return text != oldDelegate.text ||
        style != oldDelegate.style ||
        wrapMode != oldDelegate.wrapMode ||
        maxWidth != oldDelegate.maxWidth ||
        fontFamily != oldDelegate.fontFamily ||
        fontWeight != oldDelegate.fontWeight ||
        fontStyle != oldDelegate.fontStyle;
  }
}

class CustomTextWidget extends StatelessWidget {
  final String text;
  final TextStyle style;
  final WrapMode wrapMode;
  final double? width;
  final String? fontFamily;
  final FontWeight? fontWeight;
  final FontStyle? fontStyle;

  const CustomTextWidget({
    Key? key,
    required this.text,
    required this.style,
    this.wrapMode = WrapMode.word,
    this.width,
    this.fontFamily,
    this.fontWeight,
    this.fontStyle,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final painter = CustomTextPainter(
          text: text,
          style: style,
          wrapMode: wrapMode,
          maxWidth: width ?? constraints.maxWidth,
          fontFamily: fontFamily,
          fontWeight: fontWeight,
          fontStyle: fontStyle,
        );

        final size = painter.getTextSize(width ?? constraints.maxWidth);

        return CustomPaint(
          painter: painter,
          size: size,
        );
      },
    );
  }
}
